package com.example.utils;


import com.alibaba.fastjson.JSON;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;


import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class LuceneUtils {





    public static   List<Map<String, Object>> searchByKeyWord(String indexName,String field,String keyword,Integer total) throws Exception{
        IndexSearcher indexSearcher=createIndexSearcher(indexName);
        TopDocs topDocs=getQueryDoc(indexSearcher,keyword,field,total);
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        List<Document> documents=getDocumentByScore(scoreDocs,indexSearcher);
        System.out.println(documents.size());
        List<Map<String, Object>> objectMaps=getDocumentArrayToMapArray(documents);
        return objectMaps;
    }


    private static List<Map<String, Object>> getDocumentArrayToMapArray(List<Document> documentList){
        List<Map<String, Object>> mapList=new ArrayList<>(documentList.size());
        documentList.stream().forEach(e->{
            Map<String, Object> objectMap=getDocumentToMap(e);
            mapList.add(objectMap);
        });
        return mapList;
    }

    private static Map<String, Object> getDocumentToMap(Document document){
        Map<String, Object> map=new HashMap<>();
        document.forEach((k)->{
            map.put(k.name(),k.stringValue());
        });
        return map;
    }


    private static List<Document> getDocumentByScore(ScoreDoc[] scoreDocs,IndexSearcher indexSearcher) throws Exception{
        List<Document> documents=new ArrayList<>(scoreDocs.length);
        for (ScoreDoc scoreDoc : scoreDocs) {
            // 根据文档Id, 查询文档数据 -- 相当于关系数据库中根据主键Id查询数据
            Document doc = indexSearcher.doc(scoreDoc.doc);
            documents.add(doc);
        }
        return documents;
    }


    private static TopDocs getQueryDoc(IndexSearcher indexSearcher,String keyword,String field,Integer total) throws Exception{
        Query query=createQuery(keyword,field);
        TopDocs topDocs = indexSearcher.search(query, total);
        return topDocs;
    }

    private static Query createQuery(String keyword,String field) throws Exception{
        Analyzer analyzer = new StandardAnalyzer();
        QueryParser parser = new QueryParser(field, analyzer);
        return parser.parse(field+":"+keyword);
    }

    private static IndexSearcher createIndexSearcher(String indexName) throws Exception{
        Directory directory=getDirectory(indexName);
        DirectoryReader ireader = DirectoryReader.open(directory);
        return new IndexSearcher(ireader);
    }


    /**
     * 批量添加
     * @param indexName
     * @param objectMaps
     * @throws Exception
     */
    public static void addListDocumentByIndexName(String indexName,List<Map<String, Object>> objectMaps) throws Exception{
        List<Document> documents=listToDocument(objectMaps);
        IndexWriter indexWriter=getIndexWriter(indexName);
        for (int i = 0; i < documents.size(); i++) {
            Document document=documents.get(i);
            indexWriter.addDocument(document);
        }
        indexWriter.close();
    }

    /**
     * 添加单个
     * @param indexName
     * @param map
     * @throws Exception
     */
    public static void addMapDocumentByIndexName(String indexName,Map<String, Object> map) throws Exception{
        Document document=createDocument(map);
        IndexWriter indexWriter=getIndexWriter(indexName);
        indexWriter.addDocument(document);
        indexWriter.close();
    }


    /**
     * 删除
     * @param indexName
     * @param field
     * @param keysearch
     * @throws Exception
     */
    public static void delete(String indexName,String field,String keysearch) throws Exception{
        IndexWriter indexWriter=getIndexWriter(indexName);
        indexWriter.deleteDocuments(new Term(field, keysearch));
        indexWriter.commit();
        indexWriter.close();
    }

    /**
     * 更新
     * @param indexName
     * @param field
     * @param keysearch
     * @param map
     * @throws Exception
     */
    public static void update(String indexName,String field,String keysearch,Map<String, Object> map) throws Exception{
        Document doc=createDocument(map);
        IndexWriter indexWriter=getIndexWriter(indexName);
        indexWriter.updateDocument(new Term(field, keysearch), doc);
        indexWriter.commit();
        indexWriter.close();
    }

    /**
     * 添加数据通过索引名称
     * @param indexName
     * @param document
     * @throws Exception
     */
    private static void addDocumentByIndexName(String indexName,Document document) throws Exception{
        IndexWriter indexWriter=getIndexWriter(indexName);
        indexWriter.addDocument(document);
        indexWriter.close();
    }

    private static List<Document> listToDocument(List<Map<String, Object>> mapList){
        List<Document> documents=new ArrayList<>(mapList.size());
        for (int i = 0; i < mapList.size(); i++) {
            Map<String, Object> objectMap=mapList.get(i);
            Document document=createDocument(objectMap);
            documents.add(document);
        }
        return documents;
    }

    private static IndexWriterConfig analyzerCreate(){
        Analyzer analyzer = new StandardAnalyzer();
        IndexWriterConfig indexConfig = new IndexWriterConfig(Version.LUCENE_4_10_2, analyzer);
        return indexConfig;
    }

    private static Directory getDirectory(String indexName) throws Exception{
        File file=getFilePath(indexName);
        Directory directory = FSDirectory.open(file);
        return directory;
    }


    private static IndexWriter getIndexWriter(String indexName) throws Exception{
        Directory directory=getDirectory(indexName);
        System.out.println(directory);
        IndexWriterConfig indexWriterConfig=analyzerCreate();
        IndexWriter indexWriter=new IndexWriter(directory,indexWriterConfig);
        return indexWriter;
    }


    /**
     * 将map转为Document
     * @param stringObjectMap
     * @return
     */
    private static Document createDocument(Map<String, Object> stringObjectMap) {
        Document doc = new Document();
        for (Map.Entry<String, Object> objectEntry:stringObjectMap.entrySet()){
            doc.add(new StringField(objectEntry.getKey(), JSON.toJSONString(objectEntry.getValue()) , Field.Store.YES));
        }
        return doc;
    }


    /**
     * 为索引提供存储
     * @param indexPath
     * @return
     */
    private static File getFilePath(String indexPath){
       String path=PathUils.getPath();
        File file= new File(path+File.separator+indexPath);
        return file;
    }

}
